﻿using Glue;
using Glue.Internals;
using GlueTests.Builders;
using Xunit;

namespace GlueTests
{
    public class RelationDirectionSolverTest
    {
        [Fact]
        public void Should_be_None_if_readpermission_does_not_exist_on_atleast_one_property()
        {
            Run(GetMockPropertyWithoutReadPermission(),GetNormalProperty(),RelationDirection.None);
            Run(GetNormalProperty(), GetMockPropertyWithoutReadPermission(), RelationDirection.None);
        }

        [Fact]
        public void Should_be_TowardsRight_if_left_property_is_read_only()
        {
            Run(GetMockPropertyWithoutWritePermission(), GetNormalProperty(), RelationDirection.TowardsRight);
        }

        [Fact]
        public void Should_be_TowardsLeft_if_right_property_is_read_only()
        {
            Run(GetNormalProperty(), GetMockPropertyWithoutWritePermission(), RelationDirection.TowardsLeft);
        }

        [Fact]
        public void Should_be_TwoWays_normally()
        {
            Run(GetNormalProperty(), GetNormalProperty(), RelationDirection.TwoWays);
        }

        [Fact]
        public void Should_be_TwoWays_if_properties_IsNested_even_when_ReadOnly()
        {
            Run(GetNestedReadOnlyProperty(), GetNestedProperty(), RelationDirection.TwoWays);
            Run(GetNestedProperty(), GetNestedReadOnlyProperty(), RelationDirection.TwoWays);
            Run(GetNestedReadOnlyProperty(), GetNestedReadOnlyProperty(), RelationDirection.TwoWays);
        }

        private void Run(IObjectMember leftProperty, IObjectMember rightProperty, RelationDirection expectedDirection)
        {
            var solver = new RelationDirectionSolver();
            var direction = solver.GetDirection(leftProperty,rightProperty);
            Assert.Equal(expectedDirection, direction);
        }

        private IObjectMember GetNormalProperty()
        {
            return new PropertyBuilder(typeof(DomainPerson), "NormalProperty").Build();
        }

        private IObjectMember GetNestedReadOnlyProperty()
        {
            return new PropertyBuilder(typeof(DomainPerson), "NestedReadOnlyProperty").Build();
        }

        private IObjectMember GetNestedProperty()
        {
            return new PropertyBuilder(typeof (DomainPerson), "NestedProperty").Build();
        }

        private IObjectMember GetMockPropertyWithoutWritePermission()
        {
            return new PropertyBuilder(typeof(DomainPerson), "PropertyWithoutWritePermissions").Build();
        }

        private IObjectMember GetMockPropertyWithoutReadPermission()
        {
            return new PropertyBuilder(typeof(DomainPerson), "PropertyWithoutReadPermissions").Build();
        }


        public class DomainPerson
        {
            public int NormalProperty { get; set; }
            public DomainAddress NestedProperty { get; set; }
            public DomainAddress NestedReadOnlyProperty { get; private set; }
            public int PropertyWithoutWritePermissions { get; private set; }
            public int PropertyWithoutReadPermissions { private get; set; }
        }

        public class DomainAddress {}
    }
}


